package com.poobo.base.impl;

import java.io.Serializable;
import java.math.BigDecimal;
import java.math.BigInteger;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import javax.annotation.Resource;
import org.apache.log4j.Logger;
import org.hibernate.Query;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.transform.Transformers;
import org.hibernate.type.DateType;
import org.hibernate.type.FloatType;
import org.hibernate.type.IntegerType;
import org.hibernate.type.StringType;
import org.hibernate.type.Type;
import org.springframework.beans.factory.annotation.Autowired;

import com.poobo.base.IBaseDao;
import com.poobo.util.pager.Page;
import com.poobo.util.str.StrUtil;

public class BaseDaoImpl implements IBaseDao {
	
	@Autowired
	private SessionFactory sessionFactory;
	
	protected Logger log = Logger.getLogger(BaseDaoImpl.class);
	
	private Session session;

	public void setSession(Session session) {
		this.session = session;
	}
	public Session getSession() {
		return sessionFactory.getCurrentSession();
	}


	/**
	 * 增加对象
	 * 
	 * @param instance
	 */
	public void add(Object instance) {
		if (instance != null) {
			getSession().save(instance);
		}
	}

	/**
	 * 删除对象
	 * 
	 * @param instance
	 */
	public void del(Object instance) {
		if (instance != null) {
			getSession().delete(instance);
		}
	}

	/**
	 * 更新对象
	 * 
	 * @param instance
	 */
	public void update(Object instance) {
		if (instance != null) {
			getSession().update(instance);
		}
	}

	/**
	 * 根据hql语句更新对象
	 * 
	 * @param hql
	 */
	public void updateByHql(String hql, Object[] objects) {
		if (!hql.equals("")) {
			Query query = getSession().createQuery(hql);
			for (int i = 0; i < objects.length; i++) {
				query.setParameter(i, objects[i]);
			}
			query.executeUpdate();
		}
	}

	/**
	 * 根据hql查询数据
	 * 
	 * @param hql
	 * @return
	 */
	public List<?> findAll(String hql) {
		if (!hql.equals("")) {
			Session session = sessionFactory.getCurrentSession();
			return session.createQuery(hql).list();
		}
		return null;
	}

	/**
	 * HQL参数查询
	 * 
	 * @param hql
	 * @param start
	 * @param num
	 * @return
	 */
	public List<?> findByParams(String hql, Object[] objects) {
		Query query = getSession().createQuery(hql);
		if(objects!=null){
			for (int i = 0; i < objects.length; i++) {
				query.setParameter(i, objects[i].toString());
			}
		}
		return query.list();
	}
	

	/**
	 * 刷新
	 */
	public void refresh() {
		getSession().flush();
	}

	/**
	 * 获取对象对应参数的类型
	 * 
	 * @param bindValue
	 * @return
	 */
	private final Type[] typesFactory(Object[] bindValue) {
		int count = bindValue.length;
		Type[] types = new Type[count];
		for (int i = 0; i < count; i++) {
			if (bindValue[i].getClass().getName().endsWith("String")) {
				types[i] = new StringType();
			} else if (bindValue[i].getClass().getName().endsWith("Integer")) {
				types[i] = new IntegerType();
			} else if (bindValue[i].getClass().getName().endsWith("Float")) {
				types[i] = new FloatType();
			} else if (bindValue[i].getClass().getName().endsWith("Date")) {
				types[i] = new DateType();
			}
		}
		return types;
	}

	/**
	 * 根据 主键 查询某个对象
	 * 
	 * @param <E>
	 * @param c
	 * @param id
	 * @return
	 */
	@SuppressWarnings("unchecked")
	public <E> E selectObjectById(final Class c, final Serializable id) {
		// E e = (E) getSession().load(c, id);
		// return e;

		return (E) getSession().get(c, id);
	}

	/**
	 * 根据参数分页，参数为空。默认查询所有
	 * 
	 * @param hql
	 *            拼装hql
	 * @param page
	 *            当前页
	 * @param row
	 *            当前行
	 */
	@SuppressWarnings("unchecked")
	public <E> List<E> queryAccountByPager(String hql, String page,
			String rows) {
		if (StrUtil.isNull(hql) && StrUtil.isNull(page) && StrUtil.isNull(rows)) {
			throw new NullPointerException("Parameter is null!");
		}
		int currentpage = Integer.parseInt((page == null || page == "0") ? "1" : page);// 第几页
		int pagesize = Integer.parseInt((rows == null || rows == "0") ? "10" : rows);// 每页多少行

		List<E> list = getSession().createQuery(hql.toString())
				.setFirstResult((currentpage - 1) * pagesize)
				.setMaxResults(pagesize).list();

		return list;
	}

	/**
	 * 总行数
	 */
	public int queryTableCount(String hql) {
		int count = 0;
		if (StrUtil.isNotNull(hql)) {
			Query query = getSession().createQuery(hql.toString());
			count = Integer.parseInt(String.valueOf(query.list().size()));
		} else {
			throw new NullPointerException("count hql is null!");
		}
		return count;
	}

	public Long getCountByHql(String hql, Object... obj) {
		return getCountByHql(hql, Arrays.asList(obj));
	}

	public Long getCountByHql(String hql, List<Object> obj) {
		if (hql == null || "".equals(hql.trim())) {
			throw new RuntimeException("count hql is null!");
		}
		Query query = getSession().createQuery(hql);
		if (obj != null && obj.size() > 0) {
			for (int i = 0; i < obj.size(); i++) {
				query.setParameter(i, obj.get(i));
			}
		}
		List<?> list = query.list();
		if (list == null || list.size() <= 0) {
			return new Long(0);
		}
		Object o = list.get(0);
		if (o == null) {
			return 0l;
		} else if (o instanceof BigDecimal) {
			return ((BigDecimal) o).longValue();
		} else if (o instanceof BigInteger) {
			return ((BigInteger) o).longValue();
		} else if (o instanceof Long) {
			return ((Long) o).longValue();
		} else {
			return (Long) o;
		}
	}

	public Page getPageByHql(Page page) {
		page.setRowCount(getCountByHql(page.getCountHql(), page.getParam()).intValue());// 总记录数
		if (page.getBaseHql() == null || "".equals(page.getBaseHql().trim())) {
			throw new RuntimeException("base hql is null!");
		}
		Query query = getSession().createQuery(page.getBaseHql());
		if (page.getParam() != null && page.getParam().size() > 0) {
			for (int i = 0; i < page.getParam().size(); i++) {
				query.setParameter(i, page.getParam().get(i));
			}
		}
		query.setMaxResults(page.getPageSize()).setFirstResult((page.getPageNo() - 1) * page.getPageSize());
		page.setPageList(query.list());
		return page;
	}

	public Integer getCountBySql(String sql, List<Object> obj) {
		if (sql == null || "".equals(sql.trim())) {
			throw new RuntimeException("count sql is null!");
		}
		Query query = getSession().createSQLQuery(sql);
		if (obj != null && obj.size() > 0) {
			for (int i = 0; i < obj.size(); i++) {
				query.setParameter(i, obj.get(i));
			}
		}
		List<?> list = query.list();
		if (list == null || list.size() <= 0) {
			return new Integer(0);
		}
		Object o = list.get(0);
		if (o == null) {
			return 0;
		} else if (o instanceof BigDecimal) {
			return ((BigDecimal) o).intValue();
		} else if (o instanceof BigInteger) {
			return ((BigInteger) o).intValue();
		} else if (o instanceof Long) {
			return ((Long) o).intValue();
		} else {
			return (Integer) o;
		}
	}

	public Page getPageBySql(Page page) {
		page.setRowCount(getCountBySql(page.getCountSql(), page.getParam()).intValue());// 总记录数
		if (page.getBaseSql() == null || "".equals(page.getBaseSql().trim())) {
			throw new RuntimeException("base sql is null!");
		}
		Query query = getSession().createSQLQuery(page.getBaseSql());
		if (page.getParam() != null && page.getParam().size() > 0) {
			for (int i = 0; i < page.getParam().size(); i++) {
				query.setParameter(i, page.getParam().get(i));
			}
		}
		query.setMaxResults(page.getPageSize()).setFirstResult((page.getPageNo() - 1) * page.getPageSize());
		page.setPageList(query.list());
		return page;
	}

	@SuppressWarnings("unchecked")
	public <T> List<T> getListByHql(String hql, List<Object> obj) {
		Query query = getSession().createQuery(hql);
		if (obj != null && obj.size() > 0) {
			for (int i = 0; i < obj.size(); i++) {
				query.setParameter(i, obj.get(i));
			}
		}
		return query.list();
	}

	@SuppressWarnings("unchecked")
	public <T> List<T> getListByHql(String hql, Object... obj) {
		Query query = getSession().createQuery(hql);
		if (obj != null && obj.length > 0) {
			for (int i = 0; i < obj.length; i++) {
				query.setParameter(i, obj[i]);
			}
		}
		return query.list();
	}

	@SuppressWarnings("unchecked")
	public List<?> getListBySql(String sql, List<Object> obj) {
		Query query = getSession().createSQLQuery(sql);
		if (obj != null && obj.size() > 0) {
			for (int i = 0; i < obj.size(); i++) {
				query.setParameter(i, obj.get(i));
			}
		}
		return query.list();
	}

	
	@SuppressWarnings("unchecked")
	public List<Map<Object, Object>> getMapBySql(String sql, List<Object> obj) {
		Query query = getSession().createSQLQuery(sql).setResultTransformer(Transformers.ALIAS_TO_ENTITY_MAP);
		if (obj != null && obj.size() > 0) {
			for (int i = 0; i < obj.size(); i++) {
				query.setParameter(i, obj.get(i));
			}
		}
		return query.list();
	}
	
	public Page getMapPageBySql(Page page) {
		page.setRowCount(getCountBySql(page.getCountSql(), page.getParam()).intValue());// 总记录数
		if (page.getBaseSql() == null || "".equals(page.getBaseSql().trim())) {
			throw new RuntimeException("base sql is null!");
		}
		Query query = getSession().createSQLQuery(page.getBaseSql()).setResultTransformer(Transformers.ALIAS_TO_ENTITY_MAP);
		if (page.getParam() != null && page.getParam().size() > 0) {
			for (int i = 0; i < page.getParam().size(); i++) {
				query.setParameter(i, page.getParam().get(i));
			}
		}
		query.setMaxResults(page.getPageSize()).setFirstResult((page.getPageNo() - 1) * page.getPageSize());
		page.setPageList(query.list());
		return page;
	}
	

	/**
	 * 保存或者修改
	 */
	public void saveOrUpdate(Object inObject) {
		getSession().saveOrUpdate(inObject);
	}

	/**
	 * 根据sql查询
	 */
	public <E> List<E> querySQL(String sql) {
		return getSession().createSQLQuery(sql).list();
	}

	@Override
	public Object getObjectById(Class clas, Integer id) {
		return getSession().get(clas, id);
	}

	/**
	 * 检查当前对象是否存在session中
	 */
	public boolean contains(Object object) {
		getSession().contains(object);
		return false;
	}

	public void delObjectByIds(String hql) {
		getSession().createQuery(hql).executeUpdate();
	}

	public void execHql(String hql, Object... obj) {
		Query query = getSession().createQuery(hql);
		if (obj != null && obj.length > 0) {
			for (int i = 0; i < obj.length; i++) {
				query.setParameter(i, obj[i]);
			}
		}
		query.executeUpdate();
	}

	public void execSql(String sql, Object... obj) {
		Query query = getSession().createSQLQuery(sql);
		if (obj != null && obj.length > 0) {
			for (int i = 0; i < obj.length; i++) {
				query.setParameter(i, obj[i]);
			}
		}
		query.executeUpdate();
	}
}
